﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using BingVis.SilverlightClient.Common;
using System.Collections.ObjectModel;
using System.Windows.Threading;
using System.Windows;
using BingVis.SilverlightClient.GoogleTransit;

using System.ComponentModel;

namespace BingVis.SilverlightClient
{
    public class StopsListViewModel : ViewModelBase
    {
        public DelegateCommand<ITransitStop> AddStop { get; private set; }
        public DelegateCommand<string> FilterStops { get; private set; }

        private ObservableCollection<TransitStopViewModel> _originalStops { get; set; }

        private ObservableCollection<TransitStopViewModel> stops;
        public ObservableCollection<TransitStopViewModel> Stops
        {
            get { return stops; }
            private set
            {
                if (stops != value)
                {
                    stops = value;
                    OnPropertyChanged("Stops");
                }
            }
        }

        public StopsListViewModel()
        {
            _originalStops = new ObservableCollection<TransitStopViewModel>();
            AddStop = new DelegateCommand<ITransitStop>(OnAddStop, true);
            FilterStops = new DelegateCommand<string>(OnFilterStops);

            Stops = _originalStops;
        }

        private delegate void AddStopDelegate(ITransitStop stop);

        private void OnAddStop(ITransitStop stop)
        {
            if (Deployment.Current != null)
                Deployment.Current.Dispatcher.BeginInvoke(() => AddNewStop(stop));
            else
                AddNewStop(stop);
        }

        private void AddNewStop(ITransitStop stop)
        {
            if (!Stops.Any(x => x.Stop == stop))
            {                
                _originalStops.Add(new TransitStopViewModel(stop));
                AddStop.CommandExecuted = true;
            }

            if (_originalStops != Stops)
                Stops = _originalStops;
        }

        private void OnFilterStops(string parm)
        {
            BackgroundWorker filterWorker = new BackgroundWorker();
            filterWorker.WorkerReportsProgress = true;
            filterWorker.WorkerSupportsCancellation = false;
            filterWorker.DoWork += new DoWorkEventHandler(filterWorker_DoWork);
            filterWorker.ProgressChanged += new ProgressChangedEventHandler(filterWorker_ProgressChanged);
            filterWorker.RunWorkerCompleted += new RunWorkerCompletedEventHandler(filterWorker_RunWorkerCompleted);

            Stops = new ObservableCollection<TransitStopViewModel>();

            filterWorker.RunWorkerAsync(parm);            
        }

        void filterWorker_DoWork(object sender, DoWorkEventArgs e)
        {
            var worker = sender as BackgroundWorker;
            var filter = e.Argument as string ?? string.Empty;
            if (filter == string.Empty)
            {
                Stops = _originalStops;
                e.Result = 0;
                return;
            }

            filter = filter.ToLower();

            IEnumerable<TransitStopViewModel> filteredStops;
            
            worker.ReportProgress(0);

            if (!filter.StartsWith("$") && !filter.EndsWith("$"))
            {
                filteredStops = from stop in _originalStops
                                let stopColor = StopColorLookup.GetStopColors(StopNameLookup.GetStopName(stop.Stop.Name)).FirstOrDefault()
                                let routeName = stopColor == null ? "NotFound" : StopColorLookup.GetRouteFromColor(stopColor)
                                where stop.Stop.Name.Equals(filter, StringComparison.CurrentCultureIgnoreCase)
                                || stop.Stop.Name.ToLower().Contains(filter)
                                || stop.Stop.Code.ToLower().Contains(filter)
                                || stop.Stop.Description.ToLower().Contains(filter)
                                || filter.Equals(routeName, StringComparison.CurrentCultureIgnoreCase)
                                select stop;
            }
            else
            {
                // fare stop filter. e.g. "$ davis", "davis $", "$davis", "davis$", "$ green"
                filter = filter.Trim('$', ' ');
                filteredStops = from stop in _originalStops
                                let stopColor = StopColorLookup.GetStopColors(StopNameLookup.GetStopName(stop.Stop.Name)).FirstOrDefault()
                                let routeName = stopColor == null ? "NotFound" : StopColorLookup.GetRouteFromColor(stopColor)
                                where StopsWithFares.IsFareStop(stop.Stop.Name) &&
                                   (stop.Stop.Name.Equals(filter, StringComparison.CurrentCultureIgnoreCase)
                                || stop.Stop.Name.ToLower().Contains(filter)
                                || stop.Stop.Code.ToLower().Contains(filter)
                                || stop.Stop.Description.ToLower().Contains(filter))
                                || filter.Equals(routeName, StringComparison.CurrentCultureIgnoreCase)
                                select stop;

            }

            int stopCount = filteredStops.Count();
            int currCount = 0;
            foreach (var stop in filteredStops)
            {
                currCount++;
                worker.ReportProgress(stopCount / currCount, stop);
            }
            e.Result = currCount;
        }

        void filterWorker_ProgressChanged(object sender, ProgressChangedEventArgs e)
        {
            var stop = e.UserState as TransitStopViewModel;
            if (stop != null)
                Stops.Add(stop);

            OnPropertyChanged("Stops");
        }

        void filterWorker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
        {   
            OnPropertyChanged("Stops");
        }
    }

    
}
